#ifdef xxxx
#pragma once
#include <iostream>
#include <functional>
#include <string>
#include <map>
#include <algorithm>
#include <numeric>
#include <vector>
#include <sstream>
#include <cmath>
#include <ctime>
#include <array>
#include <bitset>
#include <unordered_set>
#include <unordered_map>
#include <set>
#ifndef __linux
#include <windows.h>
#endif
#include <cstdlib>
#include <unistd.h>
#include <thread>
#include <algorithm>
#include "../math/util_math.h"
#include "../math/vector3.h"
#include "tuple.h"
#include "../common/readerwriterqueue.h"

class TestC
{
public:
    TestC() {}
    ~TestC();
    enum ESkillRangeType
    {
        ESkillRangeType_Sector = 0,
        ESkillRangeType_Rect = 1,
        ESkillRangeType_Ring = 2,
        ESkillRangeType_DynamicRect = 3,
        ESkillRangeType_Infinity = 4,
        ESkillRangeType_CrossRect = 5
    };
    struct TargetScope
    {
        ESkillRangeType type;
        Vector3 position;
        Vector3 forward;
        float range_far;
        float range_low;
        float angle;
    };

    bool IsInRange(const TargetScope &scope, const Vector3 &position, float radius)
    {
        Vector3 dir = position - scope.position;

        dir.SetY(0);
        float distance = Vector3::Magnitude(dir);
        float d = scope.range_far, l = scope.range_low;
        float w = scope.angle;

        if (false)
        {
            d += radius;
            l -= radius;
            float angle = ROIsZeroNumber(distance) ? 0 : Vector3::Angle(scope.forward, dir) * 2;
            return (distance < d && distance >= l && angle <= w);
        }
        else
        {
            float fowardRot = Vector3::Angle(Vector3::forward, scope.forward);
            if (!Vector3::Clockwise(Vector3::forward, scope.forward))
                fowardRot = -fowardRot;

            if (distance > 0)
                dir.Normalize();

            float hw = w / 2.0f + radius;
            float hd = d / 2.0f + radius;
            Vector3 vecs[4];
            vecs[0].Set(-hw, 0, -hd);
            vecs[1].Set(-hw, 0, hd);
            vecs[2].Set(hw, 0, hd);
            vecs[3].Set(hw, 0, -hd);

            bool result = UtilMath::IsInRect(dir * distance, vecs, Vector3::zero, fowardRot);
            if (result)
            {
                return true;
            }
            if (scope.type != ESkillRangeType_CrossRect)
            {
                return result;
            }
            fowardRot = Vector3::Angle(Vector3::left, scope.forward);
            if (!Vector3::Clockwise(Vector3::left, scope.forward))
                fowardRot = -fowardRot;
            return UtilMath::IsInRect(dir * distance, vecs, Vector3::zero, fowardRot);
        }
    }

    void test_rect();

    std::stringstream ss;
    template <typename T>
    T convert(const char *str) noexcept
    {
        ss.clear();
        ss.str(str);

        T t;
        ss >> t;
        return t;
    }

    template <typename T>
    float convert(const std::string &str)
    {
        if (str == "")
        {
            return static_cast<T>(0);
        }
        ss.clear();
        ss.str(str);

        T t;
        ss >> t;
        return t;
        //return convert<T>(str.c_str());
    }

    void test_convert(int32_t n, const std::array<std::string, 5> &str_list)
    {
        float resf = 0.0f;
        float p = 0;

        // stof
        std::time_t start = std::time(NULL);
        for (int32_t i = 0; i < n; ++i)
        {
            resf = std::stof(str_list[i % 5]);
            //resll = std::stoll(str);

            p = i * 100.0f / n;
            if (i % 1000 == 0)
            {
                std::cout << p << "%\r";
            }
            //std::cout << resf << "\n";
        }
        std::cout << "[std::stoxxx] time passed: "
                  << std::difftime(std::time(NULL), start) << " s.\n";

        // convert<>
        start = std::time(NULL);
        for (int32_t i = 0; i < n; ++i)
        {
            //std::cout << str_list[i%5] << std::endl;
            resf = convert<float>(str_list[i % 5]);
            //resll = convert<int64_t>(str_list[i%5]);

            p = i * 100.0f / n;
            if (i % 1000 == 0)
            {
                std::cout << p << "%\r";
            }
            //std::cout << resf << "\n";
        }
        std::cout << "[stringstream] time passed: "
                  << std::difftime(std::time(NULL), start) << " s.\n";

        // strtof
        char *error_str;
        start = std::time(NULL);
        for (int32_t i = 0; i < n; ++i)
        {
            resf = std::strtof(str_list[i % 5].c_str(), &error_str);
            //resll = std::strtoll(str.c_str(), &error_str, 10);

            p = i * 100.0f / n;
            if (i % 1000 == 0)
            {
                std::cout << p << "%\r";
            }
            //std::cout << resf << "\n";
        }
        std::cout << "[strtoxxx] time passed: "
                  << std::difftime(std::time(NULL), start) << " s.\n";
    }

#define EPSINON 0.000001f
    bool IsFloatZero(float value)
    {
        std::cout << std::abs(value) << std::endl;
        return std::abs(value) <= EPSINON;
    }

#define XIsInteger(x) ((std::abs(x - (int)x) < 0.0001f) || (std::abs(x - (int)x) > (1 - 0.0001f)))

    void test_bitset()
    {
        std::bitset<1024> valid;
        std::cout << sizeof(valid) << std::endl;
        uint64_t x;
        std::cout << sizeof(x) << std::endl;
        std::cout << 1024 / 64 * 8 << std::endl;
    }

    void test_set(int32_t n)
    {
        std::unordered_set<uint64_t> uset;
        auto start = std::time(NULL);
        for (int i = 0; i < n; ++i)
        {
            uset.emplace(i);
        }
        for (int i = 0; i < n; ++i)
        {
            uset.erase(i);
        }
        std::cout << "[uset] time passed: "
                  << std::difftime(std::time(NULL), start) << " s.\n";

        std::set<uint64_t> set;
        start = std::time(NULL);
        for (int i = 0; i < n; ++i)
        {
            set.emplace(i);
        }
        for (int i = 0; i < n; ++i)
        {
            set.erase(i);
        }
        std::cout << "[set] time passed: "
                  << std::difftime(std::time(NULL), start) << " s.\n";
    }

    void test_vectorbool()
    {
        std::vector<bool> valid_check(3);
        valid_check.flip();
        for (const auto &it : valid_check)
        {
            std::cout << it << " ";
        }
        std::cout << "\n";
    }

    template <typename T>
    void func(T data)
    {
        std::cout << data.size() << "\n";
    }

    void test_template()
    {
        std::vector<bool> valid_check(3);
        std::map<int32_t, std::string> dic = {{1, "123"}};
        func<std::vector<bool>>(valid_check);
        func<std::map<int32_t, std::string>>(dic);
    }

    void test_process()
    {
        int i = 0;
        char buf[102] = "#";
        char sym[] = "|/-\\";
        for (; i <= 100; i++)
        {
            buf[i] = '#';
            printf("[%-100s][%d%%][%c]\r", buf, i, sym[i % 4]);
            fflush(stdout);
            usleep(1000000);
        }
        printf("\n");
    }

    void test_fork();

    void test_pointer();

    ////////////////////////////////////////
    // 无参特化版本
    void test_variadic_templates() {}

    // TODO 是否能共存？谁较泛化？谁较特化？
    template <typename... Types>
    void test_variadic_templates(const Types &... args)
    {
        std::cout << "args.size=" << sizeof...(args) << std::endl;

        //std::cout << firstArgs << std::endl;
        //test_variadic_templates(args...);
    }

    // 数量不定的模板参数
    template <typename T, typename... Types>
    void test_variadic_templates(const T &firstArgs, const Types &... args)
    {
        std::cout << "args.size=" << sizeof...(args) << std::endl;

        std::cout << firstArgs << std::endl;
        test_variadic_templates(args...);
    }

    ////////////////////////////////////////
    // 模板模板测试类
    template <typename T,
              template <class>
              class Container>
    class XCls
    {
    private:
        Container<T> c;

    public:
        XCls()
        {
            for (int i = 0; i < 30000; ++i)
            {
                c.insert(c.end(), T());
            }
            // TODO
            // ouput_static_data(T());
            Container<T> c1(c);
            Container<T> c2(std::move(c));
            c1.swap(c2);
        }
    };

    // 别名 alias template
    template <typename T>
    using Vec = std::vector<T, std::allocator<T>>;

    template <typename T>
    using List = std::list<T, std::allocator<T>>;

    void test_template_template_parameter();

    /// 测试lambda
    void test_lambda();

    /// 测试Tuple
    void test_tuple();

    /// 测试容器
    void test_container();

    /// 测试c++版本
    void test_cplusplus();

    /// 测试__func__
    void test_func();

    /// 行为树日志
    struct LogTagAction
    {
        LogTagAction() = default;
        std::string Type() { return " [Action] "; }
    };
    /// 战斗日志
    struct LogTagBattle
    {
        LogTagBattle() = default;
        std::string Type() { return " [Battle] "; }
    };

    /// 测试日志模板
    template <typename LogTag>
    void test_log_tag(std::string s, LogTag tag);
    template <typename LogTag>
    void test_log_tag_fmt(LogTag tag, const char *fmt, ...)
    {
        /*
        char log_buffer[1024] = {0};
        va_list ap;
        va_start(ap, fmt);
        vsnprintf(log_buffer, sizeof(log_buffer), fmt, ap);
        va_end(ap);
        test_log_tag(std::string(log_buffer), tag);
        */
    }

    /// 测试erase
    void test_erase_98();
    void test_erase_11();

    void test_distance();

    /// 测试填充算法
    void test_fill();
    /// 测试智能指针
    void test_smart_ptr();

    /// 测试事件统计
    void test_event();

    /// 测试typeid
    void test_typeid();

    /// 测试队列
    void test_readwritequeue();

    /// 测试stl::list
    void test_list();

    /// 测试ucontext
    void test_ucontext();

    /// 测试线程
    void test_thread();

    /// 测试并行计算
    void test_parallel_accumulate();
    template <typename Iterator, typename T>
    struct accumulate_block
    {
        void operator()(Iterator first, Iterator last, T &result)
        {
            result = std::accumulate(first, last, result);
        }
    };
    template <typename Iterator, typename T>
    T parallel_accumulate(Iterator first, Iterator last, T init)
    {
        unsigned long const length = std::distance(first, last);
        if (!length)
            return init;
        unsigned long const min_per_thread = 25;
        unsigned long const max_threads = (length + min_per_thread - 1) / min_per_thread;
        unsigned long const hardware_threads =
            std::thread::hardware_concurrency();
        unsigned long const num_threads =
            std::min(hardware_threads != 0 ? hardware_threads : 2, max_threads);
        unsigned long const block_size = length / num_threads;
        std::vector<T> results(num_threads);
        std::vector<std::thread> threads(num_threads - 1);
        Iterator block_start = first;
        for (unsigned long i = 0; i < (num_threads - 1); ++i)
        {
            Iterator block_end = block_start;
            std::advance(block_end, block_size);
            threads[i] = std::thread(
                accumulate_block<Iterator, T>(),
                block_start, block_end, std::ref(results[i]));
            block_start = block_end;
        }
        accumulate_block<Iterator, T>()(
            block_start, last, results[num_threads - 1]);
        std::for_each(threads.begin(), threads.end(),
                      std::mem_fn(&std::thread::join));
        return std::accumulate(results.begin(), results.end(), init);
    }
    /// 测试gettimeofday
    void test_gettimeofday();
    class RoleInfo
    {
    public:
        RoleInfo()
        {
            std::cout << "RoleInfo" << std::endl;
        }
        ~RoleInfo()
        {
            std::cout << "~RoleInfo" << std::endl;
        }
        int32_t x{0};
        int32_t y{0};
    };
    /// 测试unique_ptr
    void test_uniqueptr(RoleInfo *raw_ptr);
    void inner_test_uniqueptr(const RoleInfo &role_info);
    /// 测试atomic
    void test_atomic();

    /// 测试线程池
    void test_thread_pool();
    /**
     * @brief 测试优先队列
     */
    void test_priority_queue();

    /**
     * 测试socket
     */
    void test_socket();

    /**
     * 测试数独
     */
    void test_suduku(std::vector<int32_t> vec, size_t curr_index, int32_t value);

    /**
     * @brief 测试复利
     */
    void test_money();

    /**
     * @brief 测试时间函数
     */
    void test_time();

    /**
     * @brief 测试条件变量
     */
    void test_condition_variable();

    /**
     * @brief 测试循环
     */
    void test_loop();

    /**
     * @brief 测试fmt
     */
    void test_fmt();

    /**
     * @brief 测试协程
     */
    void test_co();

    /**
     * @brief 测试redis
     */
    void test_redis();

    /**
     * @brief 测试xlog
     */
    //void test_xlog();

    /**
     * @brief 测试rbtree
     */
    void test_rbtree();
    template<typename T>
    void test_tmp(const T &t);

    /// 测试std::for_each
    void test_foreach();
private:
    moodycamel::ReaderWriterQueue<TargetScope *> tlog_send_queue_;
    std::thread *worker_thread_{nullptr};
};
template <typename LogTag>
void TestC::test_log_tag(std::string s, LogTag tag)
{
    std::cout << s << " " << tag.Type() << std::endl;
}

//template<typename LogTag>
//LogTag tag,
// void TestC::test_log_tag_fmt(const char *fmt, ...)
// {
//     printf("%s\n", fmt);

//     char log_buffer[1024] = { 0 };
//     va_list ap;
//     va_start(ap, fmt);
//     vsnprintf(log_buffer, sizeof(log_buffer), fmt, ap);
//     vprintf(fmt, ap);
//     va_end(ap);
//     test_log_tag(std::string(log_buffer), LogTagAction());
// }
#endif 